package com.njlime.core.sdk.wechat;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.njlime.core.sdk.wechat.jsapi.AccessToken;
import com.njlime.core.sdk.wechat.jsapi.JsapiTicket;
import com.njlime.core.sdk.wechat.jsapi.WxCache;
import com.njlime.core.sdk.wechat.menu.Menu;
import com.njlime.core.sdk.wechat.open.OpenAccessToken;
import com.njlime.core.sdk.wechat.template.WxTemplate;
import com.njlime.core.utils.DateUtil;
import com.njlime.core.utils.PropertiesUtil;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.log4j.Logger;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.ConnectException;
import java.net.URL;
import java.util.Date;

/**
 * 公众平台通用接口工具类
 */
public class WeChatUtil {
    static Logger logger = Logger.getLogger(WeChatUtil.class);
    //小青柠
    /*public static final String APP_ID = "wx00637b9c4e898a1a";
    public static final String APP_SECRET = "db7120e08a8fcf3f8ee250bcfcc593e7";
    public static final String MCH_ID = "1466930502";
    public static final String MCH_KEY = "Ei0OL9o5ukCdudx7L6wZd9rJq07DZaPC";*/
    public static final String OPEN_APP_ID = "wxc878475d9b84b15e";
    public static final String OPEN_APP_SECRET = "0c9bc9e6fb06a44beea7ed1bebdc2f77";


    /**
     * 获取access_token
     *
     * @param appid     凭证
     * @param appsecret 密钥
     * @return
     */
    public static AccessToken getAccessToken(String appid, String appsecret) {
        boolean weixin = Boolean.valueOf(PropertiesUtil.readValue("/config.properties", "weixin_switch"));
        if(!weixin) {
            AccessToken accessToken = WxCache.getInstance().accessTokenMap.get(WxCache.getInstance().accessTokenKey + "_" + appid);
            long time = 0;
            long curTime = 0;
            // 第一次获取
            if (accessToken != null) {
                time = accessToken.getCreateTime();
                curTime = Long.parseLong(DateUtil.mathString(new Date()));
                logger.info("accessToken curTime-time=" + (curTime - time) + ",oldtime=" + time);
            }
            if (curTime - time > 7200 || accessToken == null) {
                String requestUrl = UrlHeader.URL_ACCESS_TOKEN.replace("APPID", appid).replace("APPSECRET", appsecret);
                JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
                // 如果请求成功
                if (null != jsonObject) {
                    accessToken = new AccessToken();
                    accessToken.setToken(jsonObject.getString("access_token"));
                    accessToken.setExpiresIn(jsonObject.getIntValue("expires_in"));
                    accessToken.setCreateTime(Long.parseLong(DateUtil.mathString(new Date())));
                    WxCache.getInstance().accessTokenMap.put(WxCache.getInstance().accessTokenKey + "_" + appid, accessToken);
                    logger.info("accessToken  time=" + accessToken.getCreateTime());
                } else {
                    logger.info("accessToken  error:" + jsonObject);
                }
            }
            return accessToken;
        }else{
            // 拼装创建菜单的url
            String url = "https://xqn.njlime.com/base/app/wechat/getWxToken?appid=" + appid;
            // 调用接口创建菜单
            JSONObject jsonObject = WeChatUtil.httpRequest(url, "POST", null);
            if (null != jsonObject && jsonObject.getIntValue("resCode") == 0) {
                JSONObject token = jsonObject.getJSONObject("resultList");
                AccessToken accessToken = new AccessToken();
                accessToken.setToken(token.getString("token"));
                return accessToken;
            }
        }
        return null;
    }

    /**
     * 调用微信JS接口的临时票据
     *
     * @param access_token 接口访问凭证
     * @return
     */
    public static JsapiTicket getJsApiTicket(String access_token, String appid) {
        boolean weixin = Boolean.valueOf(PropertiesUtil.readValue("/config.properties", "weixin_switch"));
        if(!weixin) {
            JsapiTicket jsapiTicket = WxCache.getInstance().jsapiTicketMap.get(WxCache.getInstance().jsapiTicketKey + "_" + appid);
            long time = 0;
            long curTime = 0;
            // 第一次获取
            if (jsapiTicket != null) {
                time = jsapiTicket.getCreateTime();
                curTime = Long.parseLong(DateUtil.mathString(new Date()));
                logger.info("jsapiTicket curTime-time=" + (curTime - time) + ",oldtime=" + time);
            }
            if (curTime - time > 7200 || jsapiTicket == null) {
                String requestUrl = UrlHeader.JSAPI_TICKET_URL.replace("ACCESS_TOKEN", access_token);
                // 发起GET请求获取凭证
                JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
                String ticket = null;
                try {
                    // 如果请求成功
                    if (null != jsonObject) {
                        jsapiTicket = new JsapiTicket();
                        jsapiTicket.setTicket(jsonObject.getString("ticket"));
                        jsapiTicket.setExpiresIn(jsonObject.getIntValue("expires_in"));
                        jsapiTicket.setCreateTime(Long.parseLong(DateUtil.mathString(new Date())));
                        WxCache.getInstance().jsapiTicketMap.put(WxCache.getInstance().jsapiTicketKey + "_" + appid, jsapiTicket);
                        logger.info("accessToken  time=" + jsapiTicket.getCreateTime());
                    } else {
                        logger.info("accessToken  error:" + jsonObject);
                    }
                } catch (JSONException e) {
                    // 获取token失败
                    logger.error("获取token失败:" + jsonObject.getString("errmsg"));
                }
            }
            return jsapiTicket;
        }else{
            // 拼装创建菜单的url
            String url = "https://xqn.njlime.com/base/app/wechat/getWxJsToken?appid=" + appid;
            // 调用接口创建菜单
            JSONObject jsonObject = WeChatUtil.httpRequest(url, "POST", null);
            if (null != jsonObject && jsonObject.getIntValue("resCode") == 0) {
                JSONObject token = jsonObject.getJSONObject("resultList");
                JsapiTicket jsapiTicket = new JsapiTicket();
                jsapiTicket.setTicket(token.getString("ticket"));
                return jsapiTicket;
            }
        }
        return null;
    }

    //获取openID
    public static String getOpenId(String appid, String appsecret, String code) {
        String requestUrl = UrlHeader.OPEN_ID_URL.replace("APPID", appid).replace("APPSECRET", appsecret).replace("CODE", code);
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
        return jsonObject.getString("openid");
    }

    /**
     * 获取用户信息
     *
     * @param accessToken
     * @param openid      用户唯一id
     * @return 用户的微信信息
     */
    public static WeChatUser getUserInfo(String accessToken, String openid) {
        WeChatUser user = null;
        String url = UrlHeader.URL_GET_USERINFO.replace("ACCESS_TOKEN",
                accessToken).replace("OPENID", openid);
        JSONObject jsonObject = httpRequest(url, "GET", "");
        logger.info("getUserInfo and userinfo is " + jsonObject.toString());
        if (null != jsonObject) {
            user = (WeChatUser) JSON.parseObject(jsonObject.toJSONString(), WeChatUser.class);
        }
        return user;
    }

    public static OpenAccessToken getOpenAccessToken(String appid, String appsecret, String code) {
        OpenAccessToken openAccessToken = WxCache.getInstance().openAccessTokenMap.get(WxCache.getInstance().openAccessTokenKey);
        long time = 0;
        long curTime = 0;
        // 第一次获取
        if (openAccessToken != null) {
            time = openAccessToken.getCreateTime();
            curTime = Long.parseLong(DateUtil.mathString(new Date()));
            logger.info("openAccessToken curTime-time=" + (curTime - time) + ",oldtime=" + time);

        }
        if (openAccessToken == null || curTime - time > openAccessToken.getExpires_in()) {
            String requestUrl = UrlHeader.OPEN_ACCESS_TOKEN.replace("APPID", appid).replace("SECRET", appsecret).replace("CODE", code);
            JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
            // 如果请求成功
            if (null != jsonObject) {
                logger.debug(jsonObject.toJSONString());
                openAccessToken = new OpenAccessToken();
                openAccessToken.setAccess_token(jsonObject.getString("access_token"));
                openAccessToken.setCreateTime(Long.parseLong(DateUtil.mathString(new Date())));
                openAccessToken.setExpires_in(jsonObject.getInteger("expires_in"));
                openAccessToken.setOpenid(jsonObject.getString("openid"));
                openAccessToken.setScope(jsonObject.getString("scope"));
                openAccessToken.setUnionid(jsonObject.getString("unionid"));
                openAccessToken.setRefresh_token(jsonObject.getString("refresh_token"));
                WxCache.getInstance().openAccessTokenMap.put(WxCache.getInstance().openAccessTokenKey, openAccessToken);
                logger.info("openAccessToken time=" + openAccessToken.getCreateTime());
            } else {
                logger.info("openAccessToken error:" + jsonObject);
            }
        }
        return openAccessToken;
    }

    /**
     * 创建菜单
     *
     * @param menu 菜单实例
     * @param accessToken 有效的access_token
     * @return 0表示成功，其他值表示失败
     */
    public static int createMenu(Menu menu, String accessToken) {
        int result = 0;
        // 拼装创建菜单的url
        String url = UrlHeader.CREATE_MENU_URL.replace("ACCESS_TOKEN", accessToken);
        // 将菜单对象转换成json字符串
        String jsonMenu = JSONObject.toJSONString(menu);
        // 调用接口创建菜单
        JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);
        if (null != jsonObject) {
            if (0 != jsonObject.getIntValue("errcode")) {
                result = jsonObject.getIntValue("errcode");
                logger.error("创建菜单失败:" + jsonObject.getString("errmsg"));
            }
        }
        return result;
    }

    /**
     * 获取微信菜单
     * @param accessToken
     * @return
     */
    public static JSONObject getMenu(String accessToken){
        // 拼装创建菜单的url
        String url = UrlHeader.GET_MENU_URL.replace("ACCESS_TOKEN", accessToken);
        // 调用接口创建菜单
        JSONObject jsonObject = httpRequest(url, "GET", null);
        if (null != jsonObject) {
            return jsonObject;
        }
        return null;
    }


    /**
     * 带参数二维码
     * @param accessToken
     * @return
     */
    public static JSONObject createQrCode(String accessToken,String scene_str){
        String url = UrlHeader.CREATE_QR.replace("TOKEN", accessToken);
        String jsonStr = "{\"action_name\": \"QR_LIMIT_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"" + scene_str + "\"}}}";
        return httpRequest(url, "POST", jsonStr);
    }

    /**
     * 发送模板消息
     * @param accessToken
     * @param wxTemplate
     * @return
     */
    public static JSONObject sendTemplateMessage(String accessToken, WxTemplate wxTemplate){
        String url = UrlHeader.TEMPLATE_MESSAGE.replace("TOKEN", accessToken);
        String json = JSON.toJSONString(wxTemplate);
        return httpRequest(url, "POST", json);
    }


    /**
     * 发起https请求并获取结果
     *
     * @param requestUrl    请求地址
     * @param requestMethod 请求方式（GET、POST）
     * @param outputStr     提交的数据
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    public static JSONObject httpRequest(String requestUrl,
                                         String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        StringBuffer buffer = new StringBuffer();
        try {
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            TrustManager[] tm = {new HttpsX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url
                    .openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);

            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            // 设置请求方式（GET/POST）
            httpUrlConn.setRequestMethod(requestMethod);

            if ("GET".equalsIgnoreCase(requestMethod))
                httpUrlConn.connect();

            // 当有数据需要提交时
            if (null != outputStr) {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意编码格式，防止中文乱码
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(
                    inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(
                    inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();

            jsonObject = JSON.parseObject(buffer.toString());

        } catch (ConnectException ce) {
        } catch (Exception e) {
        }
        return jsonObject;
    }

}
